package org.springframework.remoting.client;
 
import java.lang.annotation.Annotation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor;
import org.springframework.remoting.service.annotation.RemoteService;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
 
public class RemoteServiceScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware{
   protected static final Logger logger = LoggerFactory.getLogger(RemoteServiceScannerConfigurer.class);
   private ApplicationContext applicationContext;
   private String basePackage = "";
   
   private String httpInvokerRequestExecutorBeanName;
   private Class<? extends Annotation> annotationClass;
   private String rmiIp = "";
   
   private String baseUrl = "";
   
   private String serverContextPath = "";
   
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
   {
     this.applicationContext = applicationContext;
   }
   
   public String getBasePackage()
   {
     return basePackage;
   }
   
   public void setBasePackage(String basePackage) {
     this.basePackage = basePackage;
   }
   
   public final Class<? extends Annotation> getAnnotationClass() {
     return this.annotationClass;
   }
   
   public final void setAnnotationClass(Class<? extends Annotation> annotationClass)
   {
     this.annotationClass = annotationClass;
   }
   
   public final String getBaseUrl() {
     return baseUrl;
   }
   
   public void setBaseUrl(String baseUrl) {
     this.baseUrl = baseUrl;
   }
   
   public final String getServerContextPath() {
     return serverContextPath;
   }
   
   public final void setServerContextPath(String serverContextPath) {
	   this.serverContextPath = serverContextPath;
   }
   
   public final String getHttpInvokerRequestExecutorBeanName() {
	   if(StringUtils.isEmpty(this.httpInvokerRequestExecutorBeanName)){
		   return getBean("httpInvokerRequestExecutor",HttpComponentsHttpInvokerRequestExecutor.class);
	   }else{
		   return this.httpInvokerRequestExecutorBeanName; 
	   }
     
   }
   
   public final void setHttpInvokerRequestExecutorBeanName(String httpInvokerRequestExecutorBeanName)
   {
     this.httpInvokerRequestExecutorBeanName = httpInvokerRequestExecutorBeanName;
   }
   
   public void afterPropertiesSet() throws Exception
   {
     Assert.notNull(basePackage, "Property 'basePackage' is required");
     Assert.notNull(baseUrl, "Property 'baseUrl' is required");
     logger.debug("#####basePackage = {} ; baseUrl = {}", basePackage, baseUrl);
   }
   
   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
     throws BeansException
   {
     ClassPathRemoteServiceScanner scanner = new ClassPathRemoteServiceScanner(registry);
     scanner.setAnnotationClass(this.annotationClass == null ? RemoteService.class : this.annotationClass);
     scanner.setBaseUrl(baseUrl);
     scanner.setResourceLoader(this.applicationContext);
     scanner.setHttpInvokerRequestExecutorBeanName(getHttpInvokerRequestExecutorBeanName());
     scanner.registerFilters();
     scanner.scan(StringUtils.tokenizeToStringArray(basePackage, ",; \t\n"));
   }
   
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
     throws BeansException
   {}
   
   private String getBean(String beanName,Class<?> clazz){
	 //将applicationContext转换为ConfigurableApplicationContext  
	   ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;  
	     
	   // 获取bean工厂并转换为DefaultListableBeanFactory  
	   DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext  
	           .getBeanFactory();  
	     
	   // 通过BeanDefinitionBuilder创建bean定义  
	   BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(HttpComponentsHttpInvokerRequestExecutor.class);  
	     
	   // 注册bean  
	   defaultListableBeanFactory.registerBeanDefinition("httpInvokerRequestExecutor",beanDefinitionBuilder.getRawBeanDefinition());
	return beanName; 
   }
 }
